#include "generator.h"
using namespace std;
using namespace adevs;

const int Generator::DEFAULT_CARS_PER_HOUR = 300;

int Generator::vehicle_counter;

Generator::Generator(unsigned long seed):
Atomic<IO_Type>(),
	current_average_arrival(3600.0/DEFAULT_CARS_PER_HOUR),
	is_spike(false),
	t(0),
	u(seed),
	average_arival(3600.0/DEFAULT_CARS_PER_HOUR),
	spike_ratio(0.0)

{
}

void Generator::output_func(Bag<IO_Type>& yb)
{
	t += ta();
	// Output function generates a new vehicle
	Vehicle* v = new Vehicle(vehicle_counter++);
	v->t_start = t;
	IO_Type out(out_generate, (io_type*)v);
	yb.insert(out);
}

void Generator::set_time_to_next_vehicle()
{
	if (!is_spike)
	{	// Count a chance to spike
		double spike_random = u.uniform(0.0,8.0);
		if (spike_random < spike_ratio)
		{	// Spike starts. Decrease arrival time and count the length of spike.
			is_spike = true;
			//cout << "Spike starts" << endl;
			double spike_strength = u.uniform(2.0,4.0) * (spike_ratio + 1.0);
			current_average_arrival = average_arival / spike_strength;
			cars_to_spike_end = (rand() % 10) + 5 * (spike_ratio + 1.0);
		}
	}
	else
	{	// Count down cars in spike
		cars_to_spike_end--;
		if (cars_to_spike_end == 0)
		{
			// Spike ends. Return average arrival to normal value
			//cout << "Spike ends" << endl;
			is_spike = false;
			current_average_arrival = average_arival;
		}
	}

	time_to_next_vehicle = u.exponential(current_average_arrival);
	//cout << "Time to vehicle " << vehicle_counter << ": " << time_to_next_vehicle << endl;
}

